﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SimpleX.Tracing;

namespace SimpleX
{
    public class UnifyResultFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            //websocket 直接返回
            if (context.HttpContext.WebSockets.IsWebSocketRequest || context.HttpContext.Request.Path == "/ws")
                return;

            //模型验证失败 直接返回,使用Fluent返回结果
            var valid = context.ModelState.IsValid;
            if (!valid)
                return;

            //不成功,直接返回
            if (context.Result is IStatusCodeActionResult statusCodeResult && statusCodeResult.StatusCode != null)
            {
                if (statusCodeResult.StatusCode.Value < 200 || statusCodeResult.StatusCode.Value > 299)
                    return;
            }

            if (CheckVaildResult(context.Result, out var data))
            {
                bool notUnifyResult = context.ActionDescriptor.EndpointMetadata.Any(x => x.GetType() == typeof(NotUnifyResultAttribute));
                if (!notUnifyResult)
                {
                    var calcElapsed = long.TryParse(Convert.ToString(App.HttpContext.Items["__StopwatchMiddlewareWithEndpointBegin"]), out long begin);

                    var apiResponse = new UnifyResult<object>
                    {
                        Code = HttpStatusCode.OK,
                        Data = data,
                        Exts = Unify.Read(),
                        Msg = "请求成功",
                        Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                        TraceId = App.GetService<ITraceIdManager>()?.GetTraceId(),
                    };

                    var error = Unify.GetError();
                    if (error != null)
                    {
                        apiResponse.Code = HttpStatusCode.BadRequest;
                        apiResponse.Msg = error;
                    }

                    if (calcElapsed)
                        apiResponse.ElapsedMilliseconds = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - begin;

                    context.Result = new ObjectResult(apiResponse)
                    {
                        //StatusCode = (int?)apiResponse.Code,
                        //未授权401,模型验证失败400,其他全是200
                        DeclaredType = typeof(UnifyResult<object>),
                    };
                }
            }
        }

        internal static bool CheckVaildResult(IActionResult result, out object data)
        {
            data = default;

            // 排除以下结果，跳过规范化处理
            var isDataResult = result switch
            {
                ViewResult => false,
                PartialViewResult => false,
                FileResult => false,
                ChallengeResult => false,
                SignInResult => false,
                SignOutResult => false,
                RedirectToPageResult => false,
                RedirectToRouteResult => false,
                RedirectResult => false,
                RedirectToActionResult => false,
                LocalRedirectResult => false,
                ForbidResult => false,
                ViewComponentResult => false,
                PageResult => false,
                NotFoundResult => false,
                NotFoundObjectResult => false,
                _ => true,
            };

            // 目前支持返回值 ActionResult
            if (isDataResult) data = result switch
            {
                // 处理内容结果
                ContentResult content => content.Content,
                // 处理对象结果
                ObjectResult obj => obj.Value,
                // 处理 JSON 对象
                JsonResult json => json.Value,
                _ => null,
            };

            return isDataResult;
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }
}